package fr.esisar.cs420.graphproj;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;

/**
 * Le controleur gère les interactions utilisateurs et permet de faire le lien entre la vue et le model
 */
public class Controleur {
	
	/**
	 * L'attribut mod répresente les communications avec le Model, sont initialisation permet la connection avec la base de donnee
	 */
	private Modele mod;
	/**
	 * L'attribut compte répresente le Compte auquel l'utilisateur est connecte, il est egale a l'idCompte si l'utilisateur est connecte, 0 sinon
	 */
	private int compte;
	/**
	 * L'attribut directory correspond au path ou sont stocke les Photos
	 */
	String directoryBDD = new String("C:\\PICSBDD\\");
	
	/**
	 * Constructeur du Controleur, il initialise le Modele afin d'etablir la connection avec la base de donnee et s'initialise sans connection client
	 * @param st Permet de faire remonter des infomations jusqu'a la Vue
	 */
	public Controleur(StringBuilder st){
		mod=new Modele(st);
		compte=0;
	}
	
	/**
	 * Methode permettant de se deconnecter de la base de donnee 
	 * @param st Permet de faire remonter des infomations jusqu'a la Vue
	 */
	public void deconnection(StringBuilder st){
		mod.deconnection(st);
	}
	
	/**
	 * Methode permettant de se connecter a un compte en donnant son loggin et son mot de passe
	 * @param mail 	Correspond au loggin du Compte
	 * @param mdp	Contient le mot de passe rentre par l'utilisateur
	 * @param st 	Permet de faire remonter des infomations jusqu'a la Vue
	 */
	public void connectionClient(String mail,String mdp,StringBuilder st){
		StringBuilder mdp1=new StringBuilder();
		int comptetmp;
		
		System.out.println("Co: "+ mail + " , "+ mdp);
		
		//Récupération du mot de passe si le compte existe

		comptetmp=mod.connectionClient(mail,mdp1,st);
		if(comptetmp==0){
			st.replace(0, st.length(), "Account does not exist");
		}

		else if(mdp1.toString().equals(mdp.toString()) ){

			compte=comptetmp;
			st.replace(0, st.length(), "Login granted");
		}
		else{
			st.replace(0, st.length(), "Wrong Password");
		}		
	}
	
	/**
	 * Methode permettant de se deconnecter du Compte
	 * @param st 	Permet de faire remonter des infomations jusqu'a la Vue
	 */
	public void deconnectionClient(StringBuilder st){
		st.replace(0, st.length(), "Disconnected From "+compte);
		this.compte=0;
	}
	
	/**
	 * Methode permettant de s'inscrire
	 * @param mail 			Correspond au loggin du Compte
	 * @param mdp			Correspond au mot de passe du Compte
	 * @param nom 			Correspond au nom du client
	 * @param prenom		Correspond au prenom du client
	 * @param adrpostale	Correspond a l'adresse postale du Client
	 * @param st 			Permet de faire remonter des infomations jusqu'a la Vue
	 */
	public void inscription(String mail, String mdp, String nom, String prenom, String adrpostale,StringBuilder st){
		StringBuilder mdp1= new StringBuilder();
		int comptetmp;
		
		//Vérification si ce compte existe
		comptetmp=mod.connectionClient(mail,mdp1,st);
		
		if(comptetmp==0){
			mod.inscription(mail,mdp,nom,prenom,adrpostale,st);
		}
		else{
			st.replace(0, st.length(), "This account already exists");
		}
		
	}
	
	/**
	 * Methode permettant de charger une Photo sur le "serveur"
	 * @param dir 				Correspond au repertoir ou est stocke la photo
	 * @param name				Correspond au nom de la photo
	 * @param appareil			Correspond au type d'appareil avec lequel la photo a ete prise
	 * @param objectif 			Correspond au type d'objectif avec lequel la photo a ete prise
	 * @param distancefocale	Correspond a la distance focale avec laquel la photo a ete prise
	 * @param sensibiliteISO	Correspond a la sensibilite iso avec laquel la photo a ete prise
	 * @param ouverture			Correspond a l'ouverture avec laquel la photo a ete prise
	 * @param vitesseobturation Correspond a la vitesse d'obturation avec laquel la photo a ete prise
	 * @param resolution		Correspond a la resolution avec laquel la photo a ete prise
	 * @param st 				Permet de faire remonter des infomations jusqu'a la Vue
	 */
	public boolean upload(String dir,String name,String appareil, String objectif, int distancefocale,String sensibiliteISO, int ouverture, int vitesseobturation, String resolution, StringBuilder st){
		// On s'assure que le répertoire existe
		new File(directoryBDD).mkdir();
		boolean bool=false;
		String dircmp= new String(directoryBDD+"C"+compte+"\\");
		String photo= new String(dircmp+name);
		String photopath=new String("C"+compte+"\\"+name);
		
		if(compte!=0){
			new File(dircmp).mkdir();
			if(mod.getidPhoto(photo, st)==0){
				// La copie est faite
				if(copyFile(new File(dir+name), new File(photo))){
					mod.upload(photopath,appareil,objectif,distancefocale,sensibiliteISO, ouverture,vitesseobturation,resolution,compte,st);
					bool= true;
					st.replace(0, st.length(), "Photo: "+name+" uploaded in "+dircmp);
				}
			}
			else{
				st.replace(0, st.length(), "Photo already uploaded");
			}
		}
		else{
			st.replace(0, st.length(), "You have to loggin");
		}
		return bool;
	}
	
	/**
	 * Methode permettant de copier la Photo sur le "serveur"
	 * @param source	Correspond a la source
	 * @param dest		Correspond a la destination
	 * @return			Renvoi true si la copie a reussie, false sinon
	 */
	public static boolean copyFile(File source, File dest){
		try{
			// Declaration et ouverture des flux
			java.io.FileInputStream sourceFile = new java.io.FileInputStream(source);
	 
			try{
				java.io.FileOutputStream destinationFile = null;
	 
				try{
					destinationFile = new FileOutputStream(dest);
	 
					// Lecture par segment de 0.5Mo 
					byte buffer[] = new byte[512 * 1024];
					int nbLecture;
	 
					while ((nbLecture = sourceFile.read(buffer)) != -1){
						destinationFile.write(buffer, 0, nbLecture);
					}
				} finally {
					destinationFile.close();
				}
			} finally {
				sourceFile.close();
			}
		} catch (IOException e){
			e.printStackTrace();
			return false; // Erreur
		}
	 
		return true; // Résultat OK  
	}

	/**
	 * Methode permettant de creer un Album
	 * @param titre			Correspond au titre du nouvel Album
	 * @param soustitre		Correspond au sous-titre du nouvel Album
	 * @param isPublic		Permet de savoir si l'Album est partage ou non
	 * @param st 			Permet de faire remonter des infomations jusqu'a la Vue
	 */
	public void newAlbum(String titre,String soustitre,int isPublic, StringBuilder st){
		int idDocument;
		if(compte!=0){
			idDocument=mod.newDocument(compte,titre,soustitre,isPublic,st);
			mod.newAlbum(idDocument,st);
			st.replace(0, st.length(), "Album: "+titre+" created");
		}
		else{
			st.replace(0, st.length(), "You have to log in");
		}
	}
	
	/**
	 *Methode permettant de creer un Livre
	 * @param titre			Correspond au titre du nouveau Livre
	 * @param soustitre		Correspond au titre du nouveau Livre
	 * @param isPublic		Permet de savoir si le Livre est partage ou non
	 * @param postface		Correspond a la postface du nouveau Livre
	 * @param preface		Correspond a la preface du nouveau Livre
	 * @param st			Correspond au titre du nouveau Livre
	 */
	public void newLivre(String titre,String soustitre,int isPublic,String postface,String preface,StringBuilder st){
		int idDocument;
		if(compte!=0){
			idDocument=mod.newDocument(compte,titre,soustitre,isPublic,st);
			mod.newLivre(idDocument,postface,preface,st);
			st.replace(0, st.length(), "Album: "+titre+" created");
		}
		else{
			st.replace(0, st.length(), "You have to log in");
		}
	}
	
	/**
	 * Methode permettant d'ajouter une photo a un Document
	 * @param idDocument		Correspond a l'id du Document auquel on ajoute une Photo
	 * @param dir				Correspond au repertoire ou est stocke la Photo
	 * @param titre				Correspond au titre de la Photo dans le Document
	 * @param commentaire		Correspond aux commentaires associes a la Photo dans le Document
	 * @param st				Correspond au titre du nouveau Livre
	 */
	public void ajoutPhoto(int idDocument, String dir, String titre, String commentaire,StringBuilder st){
		
		int idPhoto=mod.getidPhoto(dir, st);
		mod.ajoutPhoto(idDocument,idPhoto, titre, commentaire,st);
	}
	
	/**
	 * Methode permettant de recuperer les Photos liees au Compte connecte
	 * @param st	Correspond au titre du nouveau Livre
	 * @return		Renvoi une liste chainee de Photos
	 * @see Photo
	 */
	public Photo getAccountPhotos(StringBuilder st){
		Photo ph=null;
		if(compte!=0){
			ph=mod.getAccountPhotos(compte,st);			
		}
		else{
			st.replace(0, st.length(), "You have to log in");
		}
		return ph;	
	}
	/**
	 * Methode permettant de recuperer les Photos liees a un Document(Livre ou Album)
	 * @param id	Correspond a l'id du Document dont on veut les Photos
	 * @param type	Correspond au type du Document (Livre ou Album)
	 * @param st	Correspond au titre du nouveau Livre
	 * @return		Renvoi une liste chainee de Photos
	 * @see Photo
	 */
	public Photo getDocumentPhotos(int id, Document.type type,StringBuilder st ){
		Photo ph=null;
		boolean fin= false;
		int idDocument=mod.getidDocument(id,type , st);
		System.out.println(idDocument);
		boolean possedeDoc;
		if(compte!=0){
			
			possedeDoc=mod.possedeDoc(compte, idDocument, st);
			if(possedeDoc){			
					ph=mod.getDocumentPhotos(idDocument,st);
					if(ph==null){
						st.replace(0,st.length(),"This document is empty");
						fin=true;
					}
			}
		}
		if(ph==null&&fin==false){
			if(mod.isPublic(idDocument,st)==1){
				ph=mod.getDocumentPhotos(idDocument,st);
				st.replace(0,st.length(),"This document is empty");
				fin=true;
			}
		}
		
		if(ph==null&&fin==false){
			st.replace(0,st.length(),"You don't possess this Document and it is not public");
		}		
		return ph;
	}
		
	/**
	 * Methode permettant de recuperer les Livres associes au Compte connecte
	 * @param st 			Permet de faire remonter des infomations jusqu'a la Vue
	 * @return				Renvoi la liste chainee des Livres appartenants au Compte
	 * @see	Document
	 */
	public Document getAccountLivres(StringBuilder st ){
		Document doc=null;
		if(compte!=0){
			doc=mod.getAccountLivres(compte,st);
		}
		if(doc==null){
			st.replace(0, st.length(), "You don't have any books");
		}
		return doc;

	}
	
	/**
	 * Methode permettant de recuperer les Albums associes au Compte connecte
	 * @param st 			Permet de faire remonter des infomations jusqu'a la Vue
	 * @return				Renvoi la liste chainee d'Albums appartenants au Compte
	 * @see	Document
	 */
	public Document getAccountAlbum(StringBuilder st ){
		Document doc=null;
		if(compte!=0){
			doc=mod.getAccountAlbum(compte,st);
		}
		if(doc==null){
			st.replace(0, st.length(), "You don't have any albums");
		}
		return doc;

	}
	
	/**
	 * Methode permettant de recuperer tous les Documents associes au Compte connecte
	 * @param st 			Permet de faire remonter des infomations jusqu'a la Vue
	 * @return				Renvoi la liste chainee de Documents appartenants au Compte
	 * @see	Document
	 */
	public Document getAccountAllDocuments(StringBuilder st ){
		Document phLivre=null,phAlbum=null;
		if(compte!=0){
			phLivre=mod.getAccountLivres(compte,st);
			phAlbum=mod.getAccountAlbum(compte,st);
		}
		if(phLivre==null){
			if(phAlbum==null){
				st.replace(0, st.length(), "You don't have any documents");
			}
			else  phLivre=phAlbum;
		}
		else{
			if(phAlbum!=null){
				Document phqueu=phLivre;
				while(phqueu.next!=null){
					phqueu=phqueu.next;
				}
				phqueu.next=phAlbum;
				phAlbum.prec=phqueu;
			}

		}
		return phLivre;
	}
	
	/**
	 * Methode permettant de recuperer tous les Livres publics
	 * @param st 			Permet de faire remonter des infomations jusqu'a la Vue
	 * @return				Renvoi la liste chainee des Livres publics
	 * @see	Document
	 */
	public Document getPublicLivres(StringBuilder st ){
		Document doc=null;
		if(compte!=0){
			doc=mod.getPublicLivres(st);
		}
		if(doc==null){
			st.replace(0, st.length(), "You don't have any books");
		}
		return doc;

	}
	
	/**
	 * Methode permettant de recuperer tous les Albums publics
	 * @param st 			Permet de faire remonter des infomations jusqu'a la Vue
	 * @return				Renvoi la liste chainee des Albums publics
	 * @see	Document
	 */
	public Document getPublicAlbum(StringBuilder st ){
		Document doc=null;
		if(compte!=0){
			doc=mod.getPublicAlbums(st);
		}
		if(doc==null){
			st.replace(0, st.length(), "You don't have any albums");
		}
		return doc;

	}
	
	/**
	 * Methode permettant de recuperer tous les Document publics
	 * @param st 			Permet de faire remonter des infomations jusqu'a la Vue
	 * @return				Renvoi la liste chainee des Documents publics
	 * @see	Document
	 */
	public Document getPublicDocuments(StringBuilder st){
		Document phLivre=null,phAlbum=null;
		if(compte!=0){
			phLivre=mod.getPublicLivres(st);
			phAlbum=mod.getPublicAlbums(st);
		}
		if(phLivre==null){
			if(phAlbum==null){
				st.replace(0, st.length(), "You don't have any documents");
			}
			else  phLivre=phAlbum;
		}
		else{
			if(phAlbum!=null){
				Document phqueu=phLivre;
				while(phqueu.next!=null){
					phqueu=phqueu.next;
				}
				phqueu.next=phAlbum;
				phAlbum.prec=phqueu;
			}

		}
		return phLivre;
	}
	
	/**
	 * Methode permettant de recuperer les Formats disponibles pour un type de Document
	 * @param type			Correspond au type de document dont on veut les formats
	 * @param st 			Permet de faire remonter des infomations jusqu'a la Vue
	 * @return				Renvoi une liste chainee de Formats
	 * @see Format
	 */
	public Format getFormatDocument(Format.type type ,StringBuilder st){
		Format fo=null;
		mod.getFormatsDocument(type, st);
		if(fo==null){
			st.replace(0, st.length(), "There is none avalable Format for this type of document");
		}
		return fo;
		
	}
	
	
	
}


